# 正确的选择置换表1
PC_1_TABLE = [57, 49, 41, 33, 25, 17, 9, 1, 58, 50, 42, 34, 26, 18, 10, 2, 59, 51, 43, 35, 27, 19, 11, 3,
              60, 52, 44, 36, 63, 55, 47, 39, 31, 23, 15, 7, 62, 54, 46, 38, 30, 22, 14, 6, 61, 53, 45, 37,
              29, 21, 13, 5, 28, 20, 12, 4]
# 选择置换表2
PC_2_TABLE = [14, 17, 11, 24, 1, 5, 3, 28, 15, 6, 21, 10, 23, 19, 12, 4, 26, 8, 16, 7, 27, 20, 13, 2,
              41, 52, 31, 37, 47, 55, 30, 40, 51, 45, 33, 48, 44, 49, 39, 56, 34, 53, 46, 42, 50, 36, 29, 32]


def hex_to_bin(hex_data):
    """
    将输入的十六进制数据（可以是密钥或明文等）转换为二进制数据

    输入: 十六进制的数据（无需用空格隔开）
    输出: 二进制的数据

    如果输入的字符串不符合十六进制格式，将输出提示信息并返回空字符串。
    """
    try:
        bin_data = bin(int(hex_data, 16))[2:].zfill(len(hex_data) * 4)
        return bin_data
    except ValueError:
        print("输入的不是十六进制数，请重新输入。")
        return ""


def initial_key_preparation():
    """
    初始密钥准备函数：
    功能：获取用户输入的64位十六进制初始密钥，并转换为二进制形式。

    输出：64位二进制形式的初始密钥
    """
    # hex_key = input("请输入16位十六进制的初始密钥：")
    hex_key = '133457799bbcdff1'
    bin_key = hex_to_bin(hex_key)
    if len(bin_key)!= 64:
        print("输入的密钥长度不符合要求，请重新输入。")
        return None
    return bin_key


def key_preprocessing(key):
    """
    密钥预处理函数：
    功能：接收64位的密钥，经过选择置换表1（PC - 1）的处理，将其变为56位。

    输入：64位密钥（二进制形式）。
    输出：56位处理后的密钥（二进制形式）。
    """

    result = ([int(key[PC_1_TABLE[i] - 1]) for i in range(len(PC_1_TABLE))])
    # print('PC1置换之后',result)
    return result


def key_cyclic_left_shift(key_56, round_num):
    """
    密钥循环左移函数：
    功能：针对56位的密钥（分为C0和D0两部分），根据不同的轮数对其进行相应位数的循环左移操作。

    输入：56位密钥（二进制形式，包含C0和D0部分）、轮数。
    输出：经过循环左移后的56位密钥（更新后的C0和D0部分重新拼接起来，二进制形式）。
    """
    c0, d0 = key_56[:28], key_56[28:]
    shift_amount = 1 if round_num == 0 or round_num == 1 or round_num == 8 or round_num == 15 else 2
    c0 = c0[shift_amount:] + c0[:shift_amount]
    d0 = d0[shift_amount:] + d0[:shift_amount]
    return c0 + d0


def permutation_selection_2(key_56):
    """
    置换选择2压缩函数（轮密钥生成步骤中涉及置换选择2的操作）：
    功能：经过密钥循环左移后的56位密钥，通过选择置换表2（PC - 2）进行处理，生成48位的轮密钥。

    输入：经过密钥循环左移后的56位密钥（二进制形式）。
    输出：48位的轮密钥（二进制形式）。
    """
    result = ([int(key_56[PC_2_TABLE[i] - 1]) for i in range(len(PC_2_TABLE))])
    # print('PC2置换之后',result)
    return result


def generate_DES_key():
    # 初始密钥准备
    initial_key = initial_key_preparation()
    if initial_key is not None:
        # 密钥预处理
        key_56 = key_preprocessing(initial_key)
        Round_keys = []
        for round_num in range(16):
            # 密钥循环左移
            key_56_shifted = key_cyclic_left_shift(key_56, round_num)
            # 置换选择2生成轮密钥
            row_round_key = permutation_selection_2(key_56_shifted)
            round_key = ''.join(f'{i:01b}' for i in row_round_key)
            Round_keys.append(round_key)
            # print(f"第{round_num + 1}轮的轮密钥（二进制）：{round_key}")
        # print(*(i for i in Round_keys),sep = '\n')   #遍历输出
        return Round_keys
    print('初始化后的密钥无效')

#执行函数调用
# generate_DES_key()

'''
133457799bbcdff1
'''